package store.lunangangster.nodeflow.rt.element.flow;

import static store.lunangangster.nodeflow.enums.FlowType.FLOW_WHEN;

import cn.hutool.core.collection.CollUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import store.lunangangster.nodeflow.async.ExecutorServiceDelegate;
import store.lunangangster.nodeflow.enums.FlowType;
import store.lunangangster.nodeflow.exception.ExecuteException;

/**
 * 并行执行流
 *
 * @author cwk
 * @version 1.0
 */
public class WhenFlow extends Flow {

	private boolean any;

	// need no arguments constructor
	public WhenFlow() {}

	@Override
	public void execute(Integer slotIndex) {
		if (CollUtil.isEmpty(executableList)) {
			return;
		}
		// 异步执行所有节点
		ExecutorService executor = ExecutorServiceDelegate.getWhenExecutor();
		final Integer slot = slotIndex;
		final List<CompletableFuture<Void>> futureList = new ArrayList<>(this.executableList.size());
		this.executableList.forEach(executable -> {
			futureList.add(CompletableFuture.runAsync(() -> executable.execute(slot), executor));
		});
		CompletableFuture<?> result;
		if (isAny()) {
			result = CompletableFuture.anyOf(futureList.toArray(new CompletableFuture[0]));
		} else {
			result = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
		}
		// 等待异步任务完成
		try {
			result.get();
		} catch (InterruptedException ignore) {
		} catch (ExecutionException e) {
			throw new ExecuteException("when node执行异常", e);
		}
	}

	@Override
	public FlowType getFlowType() {
		return FLOW_WHEN;
	}

	public boolean isAny() {
		return any;
	}

	public void setAny(boolean any) {
		this.any = any;
	}
}
